﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

public enum Day
{
    ZERO, ONE, TWO, THREE, FOUR, FIVE, NONE
}

public class DayManager
{
    public MapManager mapManager;
    public Day actualDay;
    public List<Interaction> listaInteracao;
    public List<Objects> objList;
    public List<NPC> npcList;

    private string GetPath
    {
        get { return Directory.GetCurrentDirectory() + "\\Content\\Days\\"; } 
    }

    public void Load(Day day)
    {
        if (mapManager == null)
            mapManager = new MapManager(GameSession.Content);

        //Console.WriteLine(GetPath);
        actualDay = day;
        LoadMaps(day);
        LoadObjects(day);
        LoadNPCs(day);
    }

    private void LoadNPCs(Day day)
    {
        npcList = new List<NPC>();

        string path = "";

        path = "Content/Days/" + GetDayString() +"/NPC/NPC.txt";

        TextReader tr = new StreamReader(path, System.Text.Encoding.Default);

        // read a line of text
        string aux = tr.ReadLine();
        while (aux.Contains("//") || aux.Equals(string.Empty))
        {
            aux = tr.ReadLine();
        }

        if (aux.Contains("<npcs>"))
        {
            //aux = tr.ReadLine();
            while (!aux.Contains("</npcs>"))
            {
                aux = tr.ReadLine();
                if (aux.Contains("<npc>"))
                {
                    NPC npc = new NPC();
                    aux = tr.ReadLine();
                    while (!aux.Contains("</npc>"))
                    {
                        if (aux.Contains("<nome>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            npc.Name = aux2[1];
                        } 
                        if (aux.Contains("<precisa>"))
                        {
                            string[] aux2 = aux.Split('"');
                            string str = aux2[1];
                            Condition cond = new Condition(str);
                            if (aux.Contains("isfalse"))
                                cond.IsTrue = false;
                            npc.Need.Add(cond);
                        }
                        if (aux.Contains("<interagivel>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            npc.Interact = bool.Parse(aux2[1]);
                        }
                        if (aux.Contains("<mapa>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            npc.Map = Int32.Parse(aux2[1]);
                            npc.Origin = new Vector2(Int32.Parse(aux2[2]), Int32.Parse(aux2[3]));
                        }
                        if (aux.Contains("<sprite>"))
                        {
                            string[] aux2 = aux.Split('"');
                            string img = aux2[1];
                            npc.Sprite = GameSession.Content.Load<Texture2D>("NPC/Sprite/" + img);
                        }
                        if (aux.Contains("<direcao>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            npc._Direction = (Direction)Int32.Parse(aux2[1]);
                        }
                        if (aux.Contains("<move>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            npc.Move = new Vector2(Int32.Parse(aux2[1]), Int32.Parse(aux2[2]));
                        }
                        if (aux.Contains("<face>"))
                        {
                            string[] aux2 = aux.Split('"');
                            string img = aux2[1];
                            npc.Face = GameSession.Content.Load<Texture2D>("NPC/Face/" + img);
                        }
                        if (aux.Contains("<area>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            npc.Area = Int32.Parse(aux2[1]);
                        }
                        if (aux.Contains("<comeco>"))
                        {
                            string[] aux2 = aux.Split(' ');

                            for (int i = 1; i < aux2.Length - 1; i ++ )
                                npc.Start.Add(Int32.Parse(aux2[i]));
                        }
                        if (aux.Contains("<pensamento>"))
                        {

                            Thought thought = new Thought();
                            aux = tr.ReadLine();
                            while (!aux.Contains("</pensamento>"))
                            {
                                if (aux.Contains("<frase>"))
                                {
                                    string[] aux2 = aux.Split('"');
                                    string sentence = aux2[1];
                                    thought.Sentence = sentence;
                                }
                                if (aux.Contains("<precisa>"))
                                {
                                    string[] aux2 = aux.Split('"');
                                    string str = aux2[1];
                                    Condition cond = new Condition(str);
                                    if (aux.Contains("isfalse"))
                                        cond.IsTrue = false;
                                    thought.Need.Add(cond);
                                }
                                if (aux.Contains("<da>"))
                                {
                                    string[] aux2 = aux.Split('"');
                                    string str = aux2[1];
                                    Condition cond = new Condition(str);
                                    if (aux.Contains("-\""))
                                        cond.ToRemove = true;
                                    thought.Give.Add(cond);
                                }

                                aux = tr.ReadLine();
                            }
                            npc.AddThought(thought);
                        }
                        if (aux.Contains("<dialogo>"))
                        {
                            Dialog d = new Dialog();
                            aux = tr.ReadLine();
                            while (!aux.Contains("</dialogo>"))
                            {
                                if (aux.Contains("<npc>"))
                                {
                                    NPCDialog dialog = new NPCDialog();
                                    aux = tr.ReadLine();
                                    while (!aux.Contains("</npc>"))
                                    {
                                        if (aux.Contains("<precisa>"))
                                        {
                                            string[] aux2 = aux.Split('"');
                                            string str = aux2[1];
                                            Condition cond = new Condition(str);
                                            if (aux.Contains("isfalse"))
                                                cond.IsTrue = false;
                                            dialog.Need.Add(cond);
                                        }
                                        if (aux.Contains("<da>"))
                                        {
                                            string[] aux2 = aux.Split('"');
                                            string str = aux2[1];
                                            Condition cond = new Condition(str); 
                                            if (aux.Contains("-\""))
                                                cond.ToRemove = true;
                                            dialog.Give.Add(cond);
                                        }
                                        /*if (aux.Contains("<atributo>"))
                                        {
                                            string[] aux2 = aux.Split(' ');
                                            string atributo = aux2[1];
                                            int qnt = Int32.Parse(aux2[2]);

                                            if (atributo.Equals("Carisma"))
                                                dialog.Atributo = Atributo.CARISMA;
                                            if (atributo.Equals("Inteligencia"))
                                                dialog.Atributo = Atributo.INTELIGENCIA;
                                            if (atributo.Equals("Percepcao"))
                                                dialog.Atributo = Atributo.PERCEPCAO;
                                            dialog.Quantidade = qnt;
                                        }*/
                                        if (aux.Contains("<fala>"))
                                        {
                                            string[] aux2 = aux.Split('"');
                                            
                                            string str = Replace(aux2[1]);
                                            dialog.Text = str;
                                        }

                                        aux = tr.ReadLine();
                                    }
                                    d.NPCDialog.Add(dialog);
                                }
                                if (aux.Contains("<player>"))
                                {
                                    PlayerDialog dialog = new PlayerDialog();
                                    aux = tr.ReadLine();
                                    while (!aux.Contains("</player>"))
                                    {
                                        if (aux.Contains("<precisa>"))
                                        {
                                            string[] aux2 = aux.Split('"');
                                            string str = aux2[1];
                                            Condition cond = new Condition(str);
                                            if (aux.Contains("isfalse"))
                                                cond.IsTrue = false;
                                            dialog.Condition.Add(cond);
                                        }
                                        /*if (aux.Contains("<atributo>"))
                                        {
                                            string[] aux2 = aux.Split(' ');
                                            string atributo = aux2[1];
                                            int qnt = Int32.Parse(aux2[2]);

                                            if (atributo.Equals("Carisma"))
                                                dialog.Atributo = Atributo.CARISMA;
                                            if (atributo.Equals("Inteligencia"))
                                                dialog.Atributo = Atributo.INTELIGENCIA;
                                            if (atributo.Equals("Percepcao"))
                                                dialog.Atributo = Atributo.PERCEPCAO;
                                            dialog.Quantidade = qnt;
                                        }*/
                                        if (aux.Contains("<fala>"))
                                        {
                                            string[] aux2 = aux.Split('"');
                                            string str = Replace(aux2[1]);
                                            dialog.Text = str;
                                        }
                                        if (aux.Contains("<proximo>"))
                                        {
                                            string[] aux2 = aux.Split(' ');

                                            for (int i = 1; i < aux2.Length - 1; i++)
                                                dialog.Next.Add(Int32.Parse(aux2[i]));
                                        }
                                        if (aux.Contains("<da>"))
                                        {
                                            string[] aux2 = aux.Split('"');
                                            string str = aux2[1];
                                            Condition cond = new Condition(str);
                                            if (aux.Contains("-\""))
                                                cond.ToRemove = true;
                                            dialog.Give.Add(cond);
                                        }
                                        aux = tr.ReadLine();
                                    }
                                    d.PlayerDialog.Add(dialog);
                                }

                                aux = tr.ReadLine();
                            }

                            npc.Dialogos.Add(npc.Dialogos.Count, d);
                        }
                        aux = tr.ReadLine();
                    }
                    npcList.Add(npc);
                }
            }
        }

        tr.Close();
    }

    private string GetDayString()
    {
        switch (actualDay)
        {
            case Day.ZERO:
                return "ZERO";
                break;
            case Day.ONE:
                return "ONE";
                break;
            case Day.TWO:
                return "TWO";
                break;
            case Day.THREE:
                return "THREE";
                break;
            case Day.FOUR:
                return "FOUR";
                break;
            case Day.FIVE:
                return "FIVE";
                break;
        }
        return "";
    }

    private string Replace(string str)
    {
        str.Replace("ç", "c");
        str.Replace("á", "a"); str.Replace("ã", "a"); str.Replace("à", "a"); str.Replace("ã", "a");
        str.Replace("é", "e");
        str.Replace("í", "i");
        str.Replace("ó", "o"); str.Replace("õ", "o");
        str.Replace("ú", "u");

        return str;
    }

    private void LoadObjects(Day day)
    {
        objList = new List<Objects>();

        listaInteracao = new List<Interaction>();

        string path = "Content/Days/" + GetDayString() + "/Object/Objetos.txt";

        TextReader tr = new StreamReader(path, System.Text.Encoding.Default);

        // read a line of text
        string aux = tr.ReadLine();
        aux = tr.ReadLine();
        while (aux.Contains("//") || aux.Equals(string.Empty))
        {
            aux = tr.ReadLine();
        }

        if (aux.Contains("<objs>"))
        {
            //aux = tr.ReadLine();
            while (!aux.Contains("</objs>"))
            {
                aux = tr.ReadLine();
                while (aux.Contains("//") || aux.Equals(string.Empty))
                {
                    aux = tr.ReadLine();
                }
                if (aux.Contains("<obj>"))
                {
                    Objects obj = new Objects(Globals.Font);
                    aux = tr.ReadLine();
                    while (!aux.Contains("</obj>"))
                    {
                        while (aux.Contains("//") || aux.Equals(string.Empty))
                        {
                            aux = tr.ReadLine();
                        }
                        if (aux.Contains("<pos>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            int x = Int32.Parse(aux2[1]);
                            int y = Int32.Parse(aux2[2]);
                            obj.Posicao = new Vector2(x, y);
                        }
                        if (aux.Contains("<img>"))
                        {
                            string[] aux2 = aux.Split('"');
                            string img = aux2[1];
                            obj.Imagem = GameSession.Content.Load<Texture2D>("Objetos/" + img);
                        }
                        if (aux.Contains("<pista>"))
                        {
                            Mensagem msg = new Mensagem();
                            string[] aux2 = aux.Split('"');
                            string pista = Replace(aux2[1]);
                            msg.Pista = pista;
                            obj.AddMessage(msg);
                        }
                        if (aux.Contains("<precisa>"))
                        {
                            string[] aux2 = aux.Split('"');
                            string str = aux2[1];
                            Condition cond = new Condition(str); 
                            if (aux.Contains("isfalse"))
                                cond.IsTrue = false;
                            obj.Condition.Add(cond);
                        }
                        if (aux.Contains("<da>"))
                        {
                            string[] aux2 = aux.Split('"');
                            string str = aux2[1];
                            Condition cond = new Condition(str);
                            if (aux.Contains("-\""))
                                cond.ToRemove = true;
                            obj.Give.Add(cond);
                        }
                        if (aux.Contains("<mensagem>"))
                        {
                            Mensagem msg = new Mensagem();
                            aux = tr.ReadLine();
                            while (!aux.Contains("</mensagem>"))
                            {
                                while (aux.Contains("//") || aux.Equals(string.Empty))
                                {
                                    aux = tr.ReadLine();
                                }

                                if (aux.Contains("<pista>"))
                                {
                                    string[] aux2 = aux.Split('"');
                                    string pista = aux2[1];
                                    msg.Pista = pista;
                                }
                                if (aux.Contains("<precisa>"))
                                {
                                    string[] aux2 = aux.Split('"');
                                    string str = aux2[1];
                                    Condition cond = new Condition(str);
                                    if (aux.Contains("isfalse"))
                                        cond.IsTrue = false;
                                    msg.Need.Add(cond);
                                }
                                if (aux.Contains("<da>"))
                                {
                                    string[] aux2 = aux.Split('"');
                                    string str = aux2[1];
                                    Condition cond = new Condition(str);
                                    if (aux.Contains("-\""))
                                        cond.ToRemove = true;
                                    msg.Give.Add(cond);
                                }

                                aux = tr.ReadLine();
                            }
                            obj.AddMessage(msg);
                        }
                        aux = tr.ReadLine();
                    }
                    objList.Add(obj);
                }
            }
        }
        

        aux = tr.ReadLine();
        while (aux.Contains("//") || aux.Equals(string.Empty))
        {
            aux = tr.ReadLine();
        }

        if (aux.Contains("<interactions>"))
        {
            aux = tr.ReadLine();
            while (!aux.Contains("</interactions>"))
            {
                /*Interaction inte = new Interaction();
                inte.Texture = GameSession.Content.Load<Texture2D>("Textures/teste");
                //List<int> list = new List<int>();
                while (aux.Contains("//") || aux.Equals(string.Empty))
                {
                    aux = tr.ReadLine();
                }
                if (aux.Contains("<objs>"))
                {

                    string[] aux2 = aux.Split(' ');
                    inte.Position = new Vector2(Int32.Parse(aux2[1]) * 64, Int32.Parse(aux2[2]) * 64);
                    for (int i = 3; i < aux2.Length - 1; i++)
                    {
                        Objects o = objList.ElementAt(Int32.Parse(aux2[i]));
                        
                        inte.ObjList.Add(o.Copy());
                    }
                    
                }
                aux = tr.ReadLine();
                listaInteracao.Add(inte);*/

                if (aux.Contains("<interaction>"))
                {
                    Interaction inte = new Interaction();
                    aux = tr.ReadLine();
                    while (!aux.Contains("</interaction>"))
                    {
                        if (aux.Contains("<pos>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            inte.MapNumber = Int32.Parse(aux2[1]);
                            int x = Int32.Parse(aux2[2]) * 64;
                            int y = Int32.Parse(aux2[3]) * 64;
                            inte.Position = new Vector2(x, y);
                        } 
                        if (aux.Contains("<posp>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            inte.MapNumber = Int32.Parse(aux2[1]);
                            int x = Int32.Parse(aux2[2]);
                            int y = Int32.Parse(aux2[3]);
                            inte.Position = new Vector2(x, y);
                        }
                        if (aux.Contains("<area>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            inte.Area = Int32.Parse(aux2[1]);
                        }
                        if (aux.Contains("<img>"))
                        {
                            string[] aux2 = aux.Split('"');
                            string img = aux2[1];
                            inte.Texture = GameSession.Content.Load<Texture2D>("Objetos/" + img);
                        }
                        if (aux.Contains("<fundo>"))
                        {
                            string[] aux2 = aux.Split('"');
                            string img = aux2[1];
                            inte.Fundo = GameSession.Content.Load<Texture2D>("Objetos/" + img);
                        }
                        if (aux.Contains("<teleporte>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            int m = Int32.Parse(aux2[1]);
                            int x = Int32.Parse(aux2[2]);
                            int y = Int32.Parse(aux2[3]);
                            inte.Teleporte = new Int32[] { m, x, y };
                        }
                        if (aux.Contains("<objs>"))
                        {
                            string[] aux2 = aux.Split(' ');
                            if (aux2.Length == 2)
                                inte.ShowTextSpace = false;

                            for (int i = 1; i < aux2.Length - 1; i++)
                            {
                                Objects o = objList.ElementAt(Int32.Parse(aux2[i]));

                                inte.ObjList.Add(o.Copy());
                            }
                        }
                        if (aux.Contains("<pensamento>"))
                        {

                            Thought thought = new Thought();
                            aux = tr.ReadLine();
                            while (!aux.Contains("</pensamento>"))
                            {
                                if (aux.Contains("<frase>"))
                                {
                                    string[] aux2 = aux.Split('"');
                                    string sentence = aux2[1];
                                    thought.Sentence = sentence;
                                }
                                if (aux.Contains("<precisa>"))
                                {
                                    string[] aux2 = aux.Split('"');
                                    string str = aux2[1];
                                    Condition cond = new Condition(str);
                                    if (aux.Contains("isfalse"))
                                        cond.IsTrue = false;
                                    thought.Need.Add(cond);
                                }
                                if (aux.Contains("<da>"))
                                {
                                    string[] aux2 = aux.Split('"');
                                    string str = aux2[1];
                                    Condition cond = new Condition(str);
                                    if (aux.Contains("-\""))
                                        cond.ToRemove = true;
                                    thought.Give.Add(cond);
                                } 
                                if (aux.Contains("<som>"))
                                {
                                    string[] aux2 = aux.Split(' ');
                                    string str = aux2[1];
                                    thought.Sound = str;
                                }

                                aux = tr.ReadLine();
                            }
                            inte.AddThought(thought);
                        }
                        aux = tr.ReadLine();
                    }
                    listaInteracao.Add(inte);
                }

                aux = tr.ReadLine();
            
            }
        }

        tr.Close();
    }

    private void LoadMaps(Day day)
    {
        string dir = GetPath + GetDayString() + "\\Map";
        string[] dirs = Directory.GetFiles(dir);
        mapManager.LoadMap(GetDayString(), (int)day,0);
    }

    /*public List<Objects> GetObjects(int listNumber)
    {
        List<Objects> list = new List<Objects>();

        foreach(int i in listaInteracao[listNumber])
        {
            Objects o = objList[i - 1];

            if (o.Atributo == Atributo.NONE)
                list.Add(o);
            if (o.Atributo == Atributo.CARISMA && GameSession.GetCarisma() >= o.Quantidade)
                list.Add(o);
            if (o.Atributo == Atributo.PERCEPCAO && GameSession.GetPercepcao() >= o.Quantidade)
                list.Add(o);
            if (o.Atributo == Atributo.INTELIGENCIA && GameSession.GetInteractionCount() >= o.Quantidade)
                list.Add(o);
        }

        return list;
    }*/


    internal bool CheckCollision(Rectangle position)
    {
        bool next = false;
        foreach(NPC npc in npcList)
        {
            if (mapManager.MapNumber != npc.Map)
                continue;

            Rectangle rec = position;

            Vector2 reccenter = new Vector2(rec.X + rec.Width / 2,
                rec.Y + rec.Height / 2);
            Vector2 npccenter = new Vector2(npc.BoundingRectangle.X + npc.BoundingRectangle.Width / 2,
                npc.BoundingRectangle.Y + npc.BoundingRectangle.Height / 2);

            if (Math.Sqrt(Math.Pow(reccenter.X - npccenter.X, 2) + Math.Pow(reccenter.Y - npccenter.Y, 2)) <= npc.Area && npc.Interact && (npc.Dialogos.Count > 0 || npc.ThoughtList.Count > 0))
            {
                GameSession.Player.IsNext = true;
                GameSession.Player.NextFrom = npc;
                next = true;
            }

            if (npc.BoundingRectangle.Intersects(rec))
                    return true;
        }
        
        //next = false;
        foreach(Interaction interaction in listaInteracao)
        {
            if (mapManager.MapNumber != interaction.MapNumber)
                continue;

            Rectangle rec = position;

            Vector2 reccenter = new Vector2(rec.X + rec.Width / 2,
                rec.Y + rec.Height / 2);
            Vector2 npccenter = new Vector2(interaction.BoundingRectangle.X + interaction.BoundingRectangle.Width / 2,
                interaction.BoundingRectangle.Y + interaction.BoundingRectangle.Height / 2);

            if (Math.Sqrt(Math.Pow(reccenter.X - npccenter.X, 2) + Math.Pow(reccenter.Y - npccenter.Y, 2)) <= interaction.Area)
            {
                GameSession.Player.IsNext = true;
                GameSession.Player.NextFromObj = interaction;
                next = true;
            }

            if (interaction.BoundingRectangle.Intersects(rec))
                return true;
        }

        if (!next)
        {
            GameSession.Player.IsNext = false;
            GameSession.Player.NextFrom = null;
            GameSession.Player.NextFromObj = null;
        }

        return mapManager.CheckCollision(position);
    }

    public void Draw(GameTime gameTime, SpriteBatch spriteBatch, int px, int py)
    {
        mapManager.Draw(spriteBatch, px, py);

        if (Globals.CheckingMap)
            return;

        List<Characters> drawList = new List<Characters>();
        drawList.Add(GameSession.Player);

        foreach (NPC npc in npcList)
        {
            if (mapManager.MapNumber == npc.Map)
            {
                drawList.Add(npc);
            }
        }

        drawList.Sort(new CharacterComparer());

        //Console.WriteLine(listaInteracao.Count);

        foreach (Interaction inte in listaInteracao)
        {
            if (mapManager.MapNumber != inte.MapNumber)
                continue;

            inte.Draw(gameTime, spriteBatch, px, py);
        }

        Player player = null;

        foreach (Characters c in drawList)
        {
            if (c.GetType() == typeof(NPC))
                ((NPC)c).Draw(gameTime, spriteBatch, px, py);
            else
            {
                player = ((Player)c);
                player.Draw(gameTime, spriteBatch);
            }
        }
    }

    internal void LoadMap(Day day, int map)
    {
        mapManager.LoadMap(GetDayString(), (int)day, map);
    }
}